package com.lincoln.utils;

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * Rest风格请求工具
 */
public class RestTemplateUtils {
    public static <Y> Y sendGet(RestTemplate restTemplate, String url, HttpServletRequest request, Class<Y> clazz) {
        Map<String, Object> params = WebParamUtils.formatRequestMap(request.getParameterMap());
        return sendGet(restTemplate, url, params, clazz);
    }

    /**
     * 清空重置restTemplate
     * @param restTemplate
     * @param flag 保留一个loadBalancerInterceptor
     */
    public static void removeRestTemplate(RestTemplate restTemplate,boolean flag){
        if (restTemplate.getInterceptors().size() > 1&&flag==true) {
            LoadBalancerInterceptor loadBalancerInterceptor = (LoadBalancerInterceptor) restTemplate.getInterceptors().get(0);
            restTemplate.getInterceptors().clear();
            restTemplate.getInterceptors().add(loadBalancerInterceptor);
        }
        if (restTemplate.getInterceptors().size() > 0&&flag==false) {
            restTemplate.getInterceptors().clear();
        }
    }

    //以下是带有basicAuthorization的请求
    public static <Y> Y sendGetByUrl(RestTemplate restTemplate, String username,String password, String url, Map<String, Object> params, Class<Y> clazz) {
        try {
            restTemplate = new RestTemplateBuilder()
                    .detectRequestFactory(false)
                    .basicAuthorization(username, password)
                    .configure(restTemplate);
            String param = "";
            if (params != null) {
                param = "?";
                for (String key : params.keySet()) {
                    param += "&" + key + "=" + params.get(key);
                }
            }
            Y y = restTemplate.getForObject(url + param, clazz);
            removeRestTemplate(restTemplate,true);
            return y;
        }catch (Exception e){
            removeRestTemplate(restTemplate,true);
            throw e;
        }
    }
    public static <Y> Y sendGet(RestTemplate restTemplate, String username,String password, String url, Map<String, Object> params, Class<Y> clazz) {
        try {
            restTemplate = new RestTemplateBuilder()
                    .detectRequestFactory(false)
                    .basicAuthorization(username, password)
                    .configure(restTemplate);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
            MultiValueMap<String, String> par = new LinkedMultiValueMap<String, String>();
            if (params != null) {
                for (String key : params.keySet()) {
                    par.add(key, String.valueOf(params.get(key)));
                }
            }
            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(par, headers);
            //  执行HTTP请求
            ResponseEntity<Y> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, clazz);
            //  输出结果
            Y y = response.getBody();
            removeRestTemplate(restTemplate,true);
            return y;
        }catch (Exception e){
            removeRestTemplate(restTemplate,true);
            throw e;
        }
    }
    public static <Y> Y sendPost(RestTemplate restTemplate, String username,String password,String url, HttpServletRequest request, Class<Y> clazz) {
        try {
            restTemplate = new RestTemplateBuilder()
                    .detectRequestFactory(false)
                    .basicAuthorization(username, password)
                    .configure(restTemplate);
            Map<String, Object> params = WebParamUtils.formatRequestMap(request.getParameterMap());
            Y y = sendPost(restTemplate, url, params, clazz);
            //删除权限
            removeRestTemplate(restTemplate,true);
            return y;
        }catch (Exception e) {
            //删除权限
            removeRestTemplate(restTemplate,true);
            throw e;
        }
    }
    public static <Y> Y sendPost(RestTemplate restTemplate, String username,String password, String url, Map<String, Object> params, Class<Y> clazz) {
        try {
            restTemplate = new RestTemplateBuilder()
                    .detectRequestFactory(false)
                    .basicAuthorization(username, password)
                    .configure(restTemplate);
            HttpHeaders headers = new HttpHeaders();
            //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
            MultiValueMap<String, String> par = new LinkedMultiValueMap<String, String>();
            if (params != null) {
                for (String key : params.keySet()) {
                    par.add(key, String.valueOf(params.get(key)));
                }
            }
            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(par, headers);
            //  执行HTTP请求
            ResponseEntity<Y> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, clazz);
            //  输出结果
            Y y =  response.getBody();
            removeRestTemplate(restTemplate,true);
            return y;
        }catch (Exception e){
            removeRestTemplate(restTemplate,true);
            throw e;
        }
    }

    //以下是无权限请求
    public static <Y> Y sendGet(RestTemplate restTemplate, String url, Map<String, Object> params, Class<Y> clazz) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> par = new LinkedMultiValueMap<String, String>();
        if (params != null) {
            for (String key : params.keySet()) {
                par.add(key, String.valueOf(params.get(key)));
            }
        }
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(par, headers);
        //  执行HTTP请求
        ResponseEntity<Y> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, clazz);
        //  输出结果
        return response.getBody();
    }

    public static <Y> Y sendGetByUrl(RestTemplate restTemplate, String url, HttpServletRequest request, Class<Y> clazz) {
        Map<String, Object> params = WebParamUtils.formatRequestMap(request.getParameterMap());
        return sendGetByUrl(restTemplate, url, params, clazz);
    }

    public static <Y> Y sendGetByUrl(RestTemplate restTemplate, String url, Map<String, Object> params, Class<Y> clazz) {
        String param = "";
        if (params != null) {
            param = "?";
            for (String key : params.keySet()) {
                param += "&" + key + "=" + params.get(key);
            }
        }
        return restTemplate.getForObject(url + param, clazz);
    }

    public static <Y> Y sendPost(RestTemplate restTemplate, String url, HttpServletRequest request, Class<Y> clazz) {
        Map<String, Object> params = WebParamUtils.formatRequestMap(request.getParameterMap());
        return sendPost(restTemplate, url, params, clazz);
    }

    public static <Y> Y sendPost(RestTemplate restTemplate, String url, Map<String, Object> params, Class<Y> clazz) {
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> par = new LinkedMultiValueMap<String, String>();
        if (params != null) {
            for (String key : params.keySet()) {
                par.add(key, String.valueOf(params.get(key)));
            }
        }
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(par, headers);
        //  执行HTTP请求
        ResponseEntity<Y> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, clazz);
        //  输出结果
        return response.getBody();
    }

    public static <Y> Y sendPut(RestTemplate restTemplate, String url, HttpServletRequest request, Class<Y> clazz) {
        Map<String, Object> params = WebParamUtils.formatRequestMap(request.getParameterMap());
        return sendPut(restTemplate, url, params, clazz);
    }

    public static <Y> Y sendPut(RestTemplate restTemplate, String url, Map<String, Object> params, Class<Y> clazz) {
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> par = new LinkedMultiValueMap<String, String>();
        if (params != null) {
            for (String key : params.keySet()) {
                par.add(key, String.valueOf(params.get(key)));
            }
        }
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(par, headers);
        //  执行HTTP请求
        ResponseEntity<Y> response = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, clazz);
        //  输出结果
        return response.getBody();
    }

    public static <Y> Y sendDelete(RestTemplate restTemplate, String url, HttpServletRequest request, Class<Y> clazz) {
        Map<String, Object> params = WebParamUtils.formatRequestMap(request.getParameterMap());
        return sendDelete(restTemplate, url, params, clazz);
    }

    public static <Y> Y sendDelete(RestTemplate restTemplate, String url, Map<String, Object> params, Class<Y> clazz) {
        String param = "";
        if (params != null && params.size() > 0) {
            param = "?";
            for (String key : params.keySet()) {
                param += "&" + key + "=" + params.get(key);
            }
        }
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> par = new LinkedMultiValueMap<String, String>();
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(par, headers);
        //  执行HTTP请求
        ResponseEntity<Y> response = restTemplate.exchange(url + param, HttpMethod.DELETE, requestEntity, clazz);
        //  输出结果
        return response.getBody();
    }
}
